﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;

namespace Matrix.Common.Utility
{
    public static class ZipHelper
    {
        /// <summary>  
        /// 创建压缩方法  
        /// </summary>  
        /// <param name="file">文件目录</param>  
        /// <param name="zipFile">保存目录</param>  
        public static bool CreateZipFile(string file, string zipFile)
        {
            var blnResult = true;

            if (!File.Exists(file))
            {
                blnResult = false;
                throw new FileNotFoundException(string.Format("文件{0}不存在!", file));
            }
            try
            {
                using (var s = new ZipOutputStream(File.Create(zipFile)))
                {
                    s.SetLevel(9); // 压缩级别 0-9  
                    //s.Password = "123"; //Zip压缩文件密码  
                    var buffer = new byte[4096]; //缓冲区大小  

                    var entry = new ZipEntry(Path.GetFileName(file)) { DateTime = DateTime.Now };
                    s.PutNextEntry(entry);
                    using (var fs = File.OpenRead(file))
                    {
                        int sourceBytes;
                        do
                        {
                            sourceBytes = fs.Read(buffer, 0, buffer.Length);
                            s.Write(buffer, 0, sourceBytes);
                        } while (sourceBytes > 0);
                    }

                    s.Finish();
                    s.Close();
                }
            }
            catch (System.Exception ex)
            {
                blnResult = false;
                throw new System.Exception(string.Format("压缩文件{0}时出现异常：{1}", file, ex));
            }

            return blnResult;
        }
        /// <summary>
        /// Zips the specified zip path.
        /// </summary>
        /// <param name="strZipPath">The zip path.</param>
        /// <param name="strZipTopDirectoryPath">The zip top directory path.</param>
        /// <param name="filesOrDirectoriesPaths">The files or directories paths.</param>
        /// <returns></returns>
        public static bool CreateZipForder(string strZipPath, string strZipTopDirectoryPath, string[] filesOrDirectoriesPaths)
        {
            try
            {
                var allFilesPath = new List<string>();
                if (filesOrDirectoriesPaths.Length > 0) // get all files path
                {
                    foreach (var t in filesOrDirectoriesPaths)
                    {
                        if (File.Exists(t))
                        {
                            allFilesPath.Add(t);
                        }
                        else if (Directory.Exists(t))
                        {
                            GetDirectoryFiles(t, allFilesPath);
                        }
                    }
                }

                if (allFilesPath.Count > 0)
                {
                    if (File.Exists(strZipPath))
                        File.Delete(strZipPath);
                    var zipOutputStream = new ZipOutputStream(File.Create(strZipPath));
                    zipOutputStream.SetLevel(9);

                    foreach (var strFile in allFilesPath.Select(t => t.ToString()))
                    {
                        try
                        {
                            if (strFile.Substring(strFile.Length - 1) == "") //folder
                            {
                                var strFileName = strFile.Replace(strZipTopDirectoryPath, "");
                                if (strFileName.StartsWith(""))
                                {
                                    strFileName = strFileName.Substring(1);
                                }
                                var entry = new ZipEntry(strFileName) { DateTime = DateTime.Now };
                                zipOutputStream.PutNextEntry(entry);
                            }
                            else //file
                            {
                                var fs = File.OpenRead(strFile);

                                var buffer = new byte[fs.Length];
                                fs.Read(buffer, 0, buffer.Length);

                                var strFileName = strFile.Replace(strZipTopDirectoryPath, "");
                                if (strFileName.StartsWith(""))
                                {
                                    strFileName = strFileName.Substring(1);
                                }
                                var entry = new ZipEntry(strFileName) { DateTime = DateTime.Now };
                                zipOutputStream.PutNextEntry(entry);
                                zipOutputStream.Write(buffer, 0, buffer.Length);

                                fs.Close();
                                fs.Dispose();
                            }
                        }
                        catch
                        {
                            continue;
                        }
                    }

                    zipOutputStream.Finish();
                    zipOutputStream.Close();

                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Gets the directory files.
        /// </summary>
        /// <param name="strParentDirectoryPath">The parent directory path.</param>
        /// <param name="allFilesPath">All files path.</param>
        private static void GetDirectoryFiles(string strParentDirectoryPath, ICollection<string> allFilesPath)
        {
            var files = Directory.GetFiles(strParentDirectoryPath);
            foreach (var t in files)
            {
                allFilesPath.Add(t);
            }
            var directorys = Directory.GetDirectories(strParentDirectoryPath);
            foreach (var t in directorys)
            {
                GetDirectoryFiles(t, allFilesPath);
            }
            if (files.Length == 0 && directorys.Length == 0) //empty folder
            {
                allFilesPath.Add(strParentDirectoryPath);
            }
        }

        public static void DeleteFolder(string dir)
        {
            if (Directory.Exists(dir)) //如果存在这个文件夹删除之
            {
                foreach (var d in Directory.GetFileSystemEntries(dir))
                {
                    if (File.Exists(d))
                        File.Delete(d); //直接删除其中的文件
                    else
                        DeleteFolder(d); //递归删除子文件夹
                }
                Directory.Delete(dir); //删除已空文件夹              
            }
            else
            {
                File.Delete(dir);
            }
        }


    }
}
